home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / HTML / TreeMenu.php < prev   
PHP Script  |  2004-03-24  |  28KB  |  813 lines

  1. <?php
  2. // +-----------------------------------------------------------------------+
  3. // | Copyright (c) 2002-2003, Richard Heyes, Harald Radi                        |
  4. // | All rights reserved.                                                  |
  5. // |                                                                       |
  6. // | Redistribution and use in source and binary forms, with or without    |
  7. // | modification, are permitted provided that the following conditions    |
  8. // | are met:                                                              |
  9. // |                                                                       |
  10. // | o Redistributions of source code must retain the above copyright      |
  11. // |   notice, this list of conditions and the following disclaimer.       |
  12. // | o Redistributions in binary form must reproduce the above copyright   |
  13. // |   notice, this list of conditions and the following disclaimer in the |
  14. // |   documentation and/or other materials provided with the distribution.|
  15. // | o The names of the authors may not be used to endorse or promote      |
  16. // |   products derived from this software without specific prior written  |
  17. // |   permission.                                                         |
  18. // |                                                                       |
  19. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
  20. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
  21. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
  22. // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
  23. // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
  24. // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
  25. // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
  26. // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
  27. // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
  28. // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
  29. // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
  30. // |                                                                       |
  31. // +-----------------------------------------------------------------------+
  32. // | Author: Richard Heyes <richard@phpguru.org>                           |
  33. // |         Harald Radi <harald.radi@nme.at>                              |
  34. // +-----------------------------------------------------------------------+
  35. //
  36. // $Id: TreeMenu.php,v 1.18 2003/12/20 13:10:59 richard Exp $
  37.  
  38. /**
  39. * HTML_TreeMenu Class
  40. *
  41. * A simple couple of PHP classes and some not so simple
  42. * Jabbascript which produces a tree menu. In IE this menu
  43. * is dynamic, with branches being collapsable. In IE5+ the
  44. * status of the collapsed/open branches persists across page
  45. * refreshes.In any other browser the tree is static. Code is
  46. * based on work of Harald Radi.
  47. *
  48. * Usage.
  49. *
  50. * After installing the package, copy the example php script to
  51. * your servers document root. Also place the TreeMenu.js and the
  52. * images folder in the same place. Running the script should
  53. * then produce the tree.
  54. *
  55. * Thanks go to Chip Chapin (http://www.chipchapin.com) for many
  56. * excellent ideas and improvements.
  57. *
  58. * @author  Richard Heyes <richard@php.net>
  59. * @author  Harald Radi <harald.radi@nme.at>
  60. * @access  public
  61. * @package HTML_TreeMenu
  62. */
  63.  
  64. class HTML_TreeMenu
  65. {
  66.     /**
  67.     * Indexed array of subnodes
  68.     * @var array
  69.     */
  70.     var $items;
  71.  
  72.     /**
  73.     * Constructor
  74.     *
  75.     * @access public
  76.     */
  77.     function HTML_TreeMenu()
  78.     {
  79.         // Not much to do here :(
  80.     }
  81.  
  82.     /**
  83.     * This function adds an item to the the tree.
  84.     *
  85.     * @access public
  86.     * @param  object $node The node to add. This object should be
  87.     *                      a HTML_TreeNode object.
  88.     * @return object       Returns a reference to the new node inside
  89.     *                      the tree.
  90.     */
  91.     function &addItem(&$node)
  92.     {
  93.         $this->items[] = &$node;
  94.         return $this->items[count($this->items) - 1];
  95.     }
  96.  
  97.     /**
  98.     * Import method for creating HTML_TreeMenu objects/structures
  99.     * out of existing tree objects/structures. Currently supported
  100.     * are Wolfram Kriesings' PEAR Tree class, and Richard Heyes' (me!)
  101.     * Tree class (available here: http://www.phpguru.org/). This
  102.     * method is intended to be used statically, eg:
  103.     * $treeMenu = &HTML_TreeMenu::createFromStructure($myTreeStructureObj);
  104.     *
  105.     * @param  array  $params   An array of parameters that determine
  106.     *                          how the import happens. This can consist of:
  107.     *                            structure   => The tree structure
  108.     *                            type        => The type of the structure, currently
  109.     *                                           can be either 'heyes' or 'kriesing'
  110.     *                            nodeOptions => Default options for each node
  111.     *                            
  112.     * @return object           The resulting HTML_TreeMenu object
  113.     */
  114.     function createFromStructure($params)
  115.     {
  116.         if (!isset($params['nodeOptions'])) {
  117.             $params['nodeOptions'] = array();
  118.         }
  119.  
  120.         switch (@$params['type']) {
  121.  
  122.             /**
  123.             * Wolfram Kriesings' PEAR Tree class
  124.             */
  125.             case 'kriesing':
  126.                 $className = strtolower(get_class($params['structure']->dataSourceClass));
  127.                 $isXMLStruct = strpos($className,'_xml') !== false ? true : false;
  128.  
  129.                 // Get the entire tree, the $nodes are sorted like in the tree view
  130.                 // from top to bottom, so we can easily put them in the nodes
  131.                 $nodes = $params['structure']->getNode();
  132.  
  133.                 // Make a new menu and fill it with the values from the tree
  134.                 $treeMenu  = new HTML_TreeMenu();
  135.                 $curNode[0] = &$treeMenu;   // we need the current node as the reference to the
  136.  
  137.                 foreach ( $nodes as $aNode ) {
  138.                     $events = array();
  139.                     $data = array();
  140.  
  141.                     // In an XML, all the attributes are saved in an array, but since they might be
  142.                     // used as the parameters, we simply extract them here if we handle an XML-structure
  143.                     if ( $isXMLStruct && sizeof($aNode['attributes']) ){
  144.                         foreach ( $aNode['attributes'] as $key=>$val ) {
  145.                             if ( !$aNode[$key] ) { // dont overwrite existing values
  146.                                 $aNode[$key] = $val;
  147.                             }
  148.                         }
  149.                     }
  150.  
  151.                     // Process all the data that are saved in $aNode and put them in the data and/or events array
  152.                     foreach ( $aNode as $key=>$val ) {
  153.                         if ( !is_array($val) ) {
  154.                             // Dont get the recursive data in here! they are always arrays
  155.                             if ( substr($key,0,2) == 'on' ){  // get the events
  156.                                 $events[$key] = $val;
  157.                             }
  158.  
  159.                             // I put it in data too, so in case an options starts with 'on' its also passed to the node ... not too cool i know
  160.                             $data[$key] = $val;
  161.                         }
  162.                     }
  163.  
  164.                     // Normally the text is in 'name' in the Tree class, so we check both but 'text' is used if found
  165.                     $data['text'] = $aNode['text'] ? $aNode['text'] : $aNode['name'];
  166.  
  167.                     // Add the item to the proper node
  168.                     $thisNode = &$curNode[$aNode['level']]->addItem( new HTML_TreeNode( $data , $events ) );
  169.                     $curNode[$aNode['level']+1] = &$thisNode;
  170.                 }
  171.                 break;
  172.  
  173.             /**
  174.             * Richard Heyes' (me!) second (array based) Tree class
  175.             */
  176.             case 'heyes_array':
  177.                 // Need to create a HTML_TreeMenu object ?
  178.                 if (!isset($params['treeMenu'])) {
  179.                     $treeMenu = &new HTML_TreeMenu();
  180.                     $parentID = 0;
  181.                 } else {
  182.                     $treeMenu = &$params['treeMenu'];
  183.                     $parentID = $params['parentID'];
  184.                 }
  185.                 
  186.                 // Loop thru the trees nodes
  187.                 foreach ($params['structure']->getChildren($parentID) as $nodeID) {
  188.                     $data = $params['structure']->getData($nodeID);
  189.                     $parentNode = &$treeMenu->addItem(new HTML_TreeNode(array_merge($params['nodeOptions'], $data)));
  190.  
  191.                     // Recurse ?
  192.                     if ($params['structure']->hasChildren($nodeID)) {
  193.                         $recurseParams['type']        = 'heyes_array';
  194.                         $recurseParams['parentID']    = $nodeID;
  195.                         $recurseParams['nodeOptions'] = $params['nodeOptions'];
  196.                         $recurseParams['structure']   = &$params['structure'];
  197.                         $recurseParams['treeMenu']    = &$parentNode;
  198.                         HTML_TreeMenu::createFromStructure($recurseParams);
  199.                     }
  200.                 }
  201.                 
  202.                 break;
  203.  
  204.             /**
  205.             * Richard Heyes' (me!) original OO based Tree class
  206.             */
  207.             case 'heyes':
  208.             default:
  209.                 // Need to create a HTML_TreeMenu object ?
  210.                 if (!isset($params['treeMenu'])) {
  211.                     $treeMenu = &new HTML_TreeMenu();
  212.                 } else {
  213.                     $treeMenu = &$params['treeMenu'];
  214.                 }
  215.                 
  216.                 // Loop thru the trees nodes
  217.                 foreach ($params['structure']->nodes->nodes as $node) {
  218.                     $tag = $node->getTag();
  219.                     $parentNode = &$treeMenu->addItem(new HTML_TreeNode(array_merge($params['nodeOptions'], $tag)));
  220.  
  221.                     // Recurse ?
  222.                     if (!empty($node->nodes->nodes)) {
  223.                         $recurseParams['structure']   = $node;
  224.                         $recurseParams['nodeOptions'] = $params['nodeOptions'];
  225.                         $recurseParams['treeMenu']    = &$parentNode;
  226.                         HTML_TreeMenu::createFromStructure($recurseParams);
  227.                     }
  228.                 }
  229.                 break;
  230.  
  231.         }
  232.  
  233.         return $treeMenu;
  234.     }
  235.     
  236.     /**
  237.     * Creates a treeMenu from XML. The structure of your XML should be
  238.     * like so:
  239.     *
  240.     * <treemenu>
  241.     *     <node text="First node" icon="folder.gif" expandedIcon="folder-expanded.gif" />
  242.     *     <node text="Second node" icon="folder.gif" expandedIcon="folder-expanded.gif">
  243.     *         <node text="Sub node" icon="folder.gif" expandedIcon="folder-expanded.gif" />
  244.     *     </node>
  245.     *     <node text="Third node" icon="folder.gif" expandedIcon="folder-expanded.gif">
  246.     * </treemenu>
  247.     *
  248.     * Any of the options you can supply to the HTML_TreeNode constructor can be supplied as
  249.     * attributes to the <node> tag. If there are no subnodes for a particular node, you can
  250.     * use the XML shortcut <node ... /> instead of <node ... ></node>. The $xml argument can
  251.     * be either the XML as a string, or an pre-created XML_Tree object. Also, this method
  252.     * REQUIRES my own Tree class to work (http://phpguru.org/tree.html). If this has not
  253.     * been include()ed or require()ed this method will die().
  254.     *
  255.     * @param  mixed  $xml  This can be either a string containing the XML, or an XML_Tree object
  256.     *                      (the PEAR::XML_Tree package).
  257.     * @return object       The HTML_TreeMenu object
  258.     */
  259.     function createFromXML($xml)
  260.     {
  261.         if (!class_exists('Tree')) {
  262.             die('Could not find Tree class');
  263.         }
  264.  
  265.         // Supplied $xml is a string
  266.         if (is_string($xml)) {
  267.             require_once('XML/Tree.php');
  268.             $xmlTree = &new XML_Tree();
  269.             $xmlTree->getTreeFromString($xml);
  270.  
  271.         // Supplied $xml is an XML_Tree object
  272.         } else {
  273.             $xmlTree = $xml;
  274.         }
  275.  
  276.         // Now process the XML_Tree object, setting the XML attributes
  277.         // to be the tag data (with out the XML tag name or contents).
  278.         $treeStructure = Tree::createFromXMLTree($xmlTree, true);
  279.         $treeStructure->nodes->traverse(create_function('&$node', '$tagData = $node->getTag(); $node->setTag($tagData["attributes"]);'));
  280.  
  281.         
  282.         return HTML_TreeMenu::createFromStructure(array('structure' => $treeStructure));
  283.     }
  284. } // HTML_TreeMenu
  285.  
  286.  
  287. /**
  288. * HTML_TreeNode class
  289. *
  290. * This class is supplementary to the above and provides a way to
  291. * add nodes to the tree. A node can have other nodes added to it.
  292. *
  293. * @author  Richard Heyes <richard@php.net>
  294. * @author  Harald Radi <harald.radi@nme.at>
  295. * @access  public
  296. * @package HTML_TreeMenu
  297. */
  298. class HTML_TreeNode
  299. {
  300.     /**
  301.     * The text for this node.
  302.     * @var string
  303.     */
  304.     var $text;
  305.  
  306.     /**
  307.     * The link for this node.
  308.     * @var string
  309.     */
  310.     var $link;
  311.  
  312.     /**
  313.     * The icon for this node.
  314.     * @var string
  315.     */
  316.     var $icon;
  317.  
  318.     /**
  319.     * The icon to show when expanded for this node.
  320.     * @var string
  321.     */
  322.     var $expandedIcon;
  323.  
  324.     /**
  325.     * The css class for this node
  326.     * @var string
  327.     */
  328.     var $cssClass;
  329.  
  330.     /**
  331.     * The link target for this node
  332.     * @var string
  333.     */
  334.     var $linkTarget;
  335.  
  336.     /**
  337.     * Indexed array of subnodes
  338.     * @var array
  339.     */
  340.     var $items;
  341.  
  342.     /**
  343.     * Whether this node is expanded or not
  344.     * @var bool
  345.     */
  346.     var $expanded;
  347.  
  348.     /**
  349.     * Whether this node is dynamic or not
  350.     * @var bool
  351.     */
  352.     var $isDynamic;
  353.  
  354.     /**
  355.     * Should this node be made visible?
  356.     * @var bool
  357.     */
  358.     var $ensureVisible;
  359.  
  360.     /**
  361.     * The parent node. Null if top level
  362.     * @var object
  363.     */
  364.     var $parent;
  365.  
  366.     /**
  367.     * Javascript event handlers;
  368.     * @var array
  369.     */
  370.     var $events;
  371.  
  372.     /**
  373.     * Constructor
  374.     *
  375.     * @access public
  376.     * @param  array $options An array of options which you can pass to change
  377.     *                        the way this node looks/acts. This can consist of:
  378.     *                         o text          The title of the node, defaults to blank
  379.     *                         o link          The link for the node, defaults to blank
  380.     *                         o icon          The icon for the node, defaults to blank
  381.     *                         o expandedIcon  The icon to show when the node is expanded
  382.     *                         o cssClass      The CSS class for this node, defaults to blank
  383.     *                         o expanded      The default expanded status of this node, defaults to false
  384.     *                                         This doesn't affect non dynamic presentation types
  385.     *                         o linkTarget    Target for the links. Defaults to linkTarget of the
  386.     *                                         HTML_TreeMenu_Presentation.
  387.     *                         o isDynamic     If this node is dynamic or not. Only affects
  388.     *                                         certain presentation types.
  389.     *                         o ensureVisible If true this node will be made visible despite the expanded
  390.     *                                         settings, and client side persistence. Will not affect
  391.     *                                         some presentation styles, such as Listbox. Default is false
  392.     * @param  array $events An array of javascript events and the corresponding event handlers.
  393.     *                       Additionally to the standard javascript events you can specify handlers
  394.     *                       for the 'onexpand', 'oncollapse' and 'ontoggle' events which will be fired
  395.     *                       whenever a node is collapsed and/or expanded.
  396.     */
  397.     function HTML_TreeNode($options = array(), $events = array())
  398.     {
  399.         $this->text          = '';
  400.         $this->link          = '';
  401.         $this->icon          = '';
  402.         $this->expandedIcon  = '';
  403.         $this->cssClass      = '';
  404.         $this->expanded      = false;
  405.         $this->isDynamic     = true;
  406.         $this->ensureVisible = false;
  407.         $this->linkTarget    = null;
  408.  
  409.         $this->parent        = null;
  410.         $this->events        = $events;
  411.  
  412.         foreach ($options as $option => $value) {
  413.             $this->$option = $value;
  414.         }
  415.     }
  416.  
  417.     /**
  418.     * Allows setting of various parameters after the initial
  419.     * constructor call. Possible options you can set are:
  420.     *  o text
  421.     *  o link
  422.     *  o icon
  423.     *  o cssClass
  424.     *  o expanded
  425.     *  o isDynamic
  426.     *  o ensureVisible
  427.     * ie The same options as in the constructor
  428.     *
  429.     * @access public
  430.     * @param  string $option Option to set
  431.     * @param  string $value  Value to set the option to
  432.     */
  433.     function setOption($option, $value)
  434.     {
  435.         $this->$option = $value;
  436.     }
  437.  
  438.     /**
  439.     * Adds a new subnode to this node.
  440.     *
  441.     * @access public
  442.     * @param  object $node The new node
  443.     */
  444.     function &addItem(&$node)
  445.     {
  446.         $node->parent  = &$this;
  447.         $this->items[] = &$node;
  448.  
  449.         /**
  450.         * If the subnode has ensureVisible set it needs
  451.         * to be handled, and all parents set accordingly.
  452.         */
  453.         if ($node->ensureVisible) {
  454.             $this->_ensureVisible();
  455.         }
  456.  
  457.         return $this->items[count($this->items) - 1];
  458.     }
  459.  
  460.     /**
  461.     * Private function to handle ensureVisible stuff
  462.     *
  463.     * @access private
  464.     */
  465.     function _ensureVisible()
  466.     {
  467.         $this->ensureVisible = true;
  468.         $this->expanded      = true;
  469.  
  470.         if (!is_null($this->parent)) {
  471.             $this->parent->_ensureVisible();
  472.         }
  473.     }
  474. } // HTML_TreeNode
  475.  
  476.  
  477. /**
  478. * HTML_TreeMenu_Presentation class
  479. *
  480. * Base class for other presentation classes to
  481. * inherit from.
  482. */
  483. class HTML_TreeMenu_Presentation
  484. {
  485.     /**
  486.     * The TreeMenu structure
  487.     * @var object
  488.     */
  489.     var $menu;
  490.  
  491.     /**
  492.     * Base constructor simply sets the menu object
  493.     *
  494.     * @param object $structure The menu structure
  495.     */
  496.     function HTML_TreeMenu_Presentation(&$structure)
  497.     {
  498.         $this->menu = &$structure;
  499.     }
  500.  
  501.     /**
  502.     * Prints the HTML generated by the toHTML() method.
  503.     * toHTML() must therefore be defined by the derived
  504.     * class.
  505.     *
  506.     * @access public
  507.     * @param  array  Options to set. Any options taken by
  508.     *                the presentation class can be specified
  509.     *                here.
  510.     */
  511.     function printMenu($options = array())
  512.     {
  513.         foreach ($options as $option => $value) {
  514.             $this->$option = $value;
  515.         }
  516.  
  517.         echo $this->toHTML();
  518.     }
  519. }
  520.  
  521.  
  522. /**
  523. * HTML_TreeMenu_DHTML class
  524. *
  525. * This class is a presentation class for the tree structure
  526. * created using the TreeMenu/TreeNode. It presents the
  527. * traditional tree, static for browsers that can't handle
  528. * the DHTML.
  529. */
  530. class HTML_TreeMenu_DHTML extends HTML_TreeMenu_Presentation
  531. {
  532.     /**
  533.     * Dynamic status of the treemenu. If true (default) this has no effect. If
  534.     * false it will override all dynamic status vars and set the menu to be
  535.     * fully expanded an non-dynamic.
  536.     */
  537.     var $isDynamic;
  538.  
  539.     /**
  540.     * Path to the images
  541.     * @var string
  542.     */
  543.     var $images;
  544.  
  545.     /**
  546.     * Target for the links generated
  547.     * @var string
  548.     */
  549.     var $linkTarget;
  550.  
  551.     /**
  552.     * Whether to use clientside persistence or not
  553.     * @var bool
  554.     */
  555.     var $userPersistence;
  556.  
  557.     /**
  558.     * The default CSS class for the nodes
  559.     */
  560.     var $defaultClass;
  561.  
  562.     /**
  563.     * Whether to skip first level branch images
  564.     * @var bool
  565.     */
  566.     var $noTopLevelImages;
  567.  
  568.     /**
  569.     * Constructor, takes the tree structure as
  570.     * an argument and an array of options which
  571.     * can consist of:
  572.     *  o images            -  The path to the images folder. Defaults to "images"
  573.     *  o linkTarget        -  The target for the link. Defaults to "_self"
  574.     *  o defaultClass      -  The default CSS class to apply to a node. Default is none.
  575.     *  o usePersistence    -  Whether to use clientside persistence. This persistence
  576.     *                         is achieved using cookies. Default is true.
  577.     *  o noTopLevelImages  -  Whether to skip displaying the first level of images if
  578.     *                         there is multiple top level branches.
  579.     *  o maxDepth          -  The maximum depth of indentation. Useful for ensuring
  580.     *                         deeply nested trees don't go way off to the right of your
  581.     *                         page etc. Defaults to no limit.
  582.     *
  583.     * And also a boolean for whether the entire tree is dynamic or not.
  584.     * This overrides any perNode dynamic settings.
  585.     *
  586.     * @param object $structure The menu structure
  587.     * @param array  $options   Array of options
  588.     * @param bool   $isDynamic Whether the tree is dynamic or not
  589.     */
  590.     function HTML_TreeMenu_DHTML(&$structure, $options = array(), $isDynamic = true)
  591.     {
  592.         $this->HTML_TreeMenu_Presentation($structure);
  593.         $this->isDynamic = $isDynamic;
  594.  
  595.         // Defaults
  596.         $this->images           = 'images';
  597.         $this->maxDepth         = 0;        // No limit
  598.         $this->linkTarget       = '_self';
  599.         $this->defaultClass     = '';
  600.         $this->usePersistence   = true;
  601.         $this->noTopLevelImages = false;
  602.  
  603.         foreach ($options as $option => $value) {
  604.             $this->$option = $value;
  605.         }
  606.     }
  607.  
  608.     /**
  609.     * Returns the HTML for the menu. This method can be
  610.     * used instead of printMenu() to use the menu system
  611.     * with a template system.
  612.     *
  613.     * @access public
  614.     * @return string The HTML for the menu
  615.     */
  616.     function toHTML()
  617.     {
  618.         static $count = 0;
  619.         $menuObj     = 'objTreeMenu_' . ++$count;
  620.  
  621.         $html  = "\n";
  622.         $html .= '<script language="javascript" type="text/javascript">' . "\n\t";
  623.         $html .= sprintf('%s = new TreeMenu("%s", "%s", "%s", "%s", %s, %s);',
  624.                          $menuObj,
  625.                          $this->images,
  626.                          $menuObj,
  627.                          $this->linkTarget,
  628.                          $this->defaultClass,
  629.                          $this->usePersistence ? 'true' : 'false',
  630.                          $this->noTopLevelImages ? 'true' : 'false');
  631.  
  632.         $html .= "\n";
  633.  
  634.         /**
  635.         * Loop through subnodes
  636.         */
  637.         if (isset($this->menu->items)) {
  638.             for ($i=0; $i<count($this->menu->items); $i++) {
  639.                 $html .= $this->_nodeToHTML($this->menu->items[$i], $menuObj);
  640.             }
  641.         }
  642.  
  643.         $html .= sprintf("\n\t%s.drawMenu();", $menuObj);
  644.         $html .= sprintf("\n\t%s.writeOutput();", $menuObj);
  645.  
  646.         if ($this->usePersistence && $this->isDynamic) {
  647.             $html .= sprintf("\n\t%s.resetBranches();", $menuObj);
  648.         }
  649.         $html .= "\n</script>";
  650.  
  651.         return $html;
  652.     }
  653.  
  654.     /**
  655.     * Prints a node of the menu
  656.     *
  657.     * @access private
  658.     */
  659.     function _nodeToHTML($nodeObj, $prefix, $return = 'newNode', $currentDepth = 0, $maxDepthPrefix = null)
  660.     {
  661.         $prefix = empty($maxDepthPrefix) ? $prefix : $maxDepthPrefix;
  662.         
  663.         $expanded  = $this->isDynamic ? ($nodeObj->expanded  ? 'true' : 'false') : 'true';
  664.         $isDynamic = $this->isDynamic ? ($nodeObj->isDynamic ? 'true' : 'false') : 'false';
  665.         $html = sprintf("\t %s = %s.addItem(new TreeNode('%s', %s, %s, %s, %s, '%s', '%s', %s));\n",
  666.                         $return,
  667.                         $prefix,
  668.                         str_replace("'", "\\'", $nodeObj->text),
  669.                         !empty($nodeObj->icon) ? "'" . $nodeObj->icon . "'" : 'null',
  670.                         !empty($nodeObj->link) ? "'" . $nodeObj->link . "'" : 'null',
  671.                         $expanded,
  672.                         $isDynamic,
  673.                         $nodeObj->cssClass,
  674.                         $nodeObj->linkTarget,
  675.                         !empty($nodeObj->expandedIcon) ? "'" . $nodeObj->expandedIcon . "'" : 'null');
  676.  
  677.         foreach ($nodeObj->events as $event => $handler) {
  678.             $html .= sprintf("\t %s.setEvent('%s', '%s');\n",
  679.                              $return,
  680.                              $event,
  681.                              str_replace(array("\r", "\n", "'"), array('\r', '\n', "\'"), $handler));
  682.         }
  683.  
  684.         if ($this->maxDepth > 0 AND $currentDepth == $this->maxDepth) {
  685.             $maxDepthPrefix = $prefix;
  686.         }
  687.  
  688.         /**
  689.         * Loop through subnodes
  690.         */
  691.         if (!empty($nodeObj->items)) {
  692.             for ($i=0; $i<count($nodeObj->items); $i++) {
  693.                 $html .= $this->_nodeToHTML($nodeObj->items[$i], $return, $return . '_' . ($i + 1), $currentDepth + 1, $maxDepthPrefix);
  694.             }
  695.         }
  696.  
  697.         return $html;
  698.     }
  699. } // End class HTML_TreeMenu_DHTML
  700.  
  701.  
  702. /**
  703. * HTML_TreeMenu_Listbox class
  704. *
  705. * This class presents the menu as a listbox
  706. */
  707. class HTML_TreeMenu_Listbox extends HTML_TreeMenu_Presentation
  708. {
  709.     /**
  710.     * The text that is displayed in the first option
  711.     * @var string
  712.     */
  713.     var $promoText;
  714.  
  715.     /**
  716.     * The character used for indentation
  717.     * @var string
  718.     */
  719.     var $indentChar;
  720.  
  721.     /**
  722.     * How many of the indent chars to use
  723.     * per indentation level
  724.     * @var integer
  725.     */
  726.     var $indentNum;
  727.  
  728.     /**
  729.     * Target for the links generated
  730.     * @var string
  731.     */
  732.     var $linkTarget;
  733.  
  734.     /**
  735.     * Constructor
  736.     *
  737.     * @param object $structure The menu structure
  738.     * @param array  $options   Options whic affect the display of the listbox.
  739.     *                          These can consist of:
  740.     *                           o promoText  The text that appears at the the top of the listbox
  741.     *                                        Defaults to "Select..."
  742.     *                           o indentChar The character to use for indenting the nodes
  743.     *                                        Defaults to " "
  744.     *                           o indentNum  How many of the indentChars to use per indentation level
  745.     *                                        Defaults to 2
  746.     *                           o linkTarget Target for the links. Defaults to "_self"
  747.     *                           o submitText Text for the submit button. Defaults to "Go"
  748.     */
  749.     function HTML_TreeMenu_Listbox($structure, $options = array())
  750.     {
  751.         $this->HTML_TreeMenu_Presentation($structure);
  752.  
  753.         $this->promoText  = 'Select...';
  754.         $this->indentChar = ' ';
  755.         $this->indentNum  = 2;
  756.         $this->linkTarget = '_self';
  757.         $this->submitText = 'Go';
  758.  
  759.         foreach ($options as $option => $value) {
  760.             $this->$option = $value;
  761.         }
  762.     }
  763.  
  764.     /**
  765.     * Returns the HTML generated
  766.     */
  767.     function toHTML()
  768.     {
  769.         static $count = 0;
  770.         $nodeHTML = '';
  771.  
  772.         /**
  773.         * Loop through subnodes
  774.         */
  775.         if (isset($this->menu->items)) {
  776.             for ($i=0; $i<count($this->menu->items); $i++) {
  777.                 $nodeHTML .= $this->_nodeToHTML($this->menu->items[$i]);
  778.             }
  779.         }
  780.  
  781.         return sprintf('<form target="%s" action="" onsubmit="var link = this.%s.options[this.%s.selectedIndex].value; if (link) {this.action = link; return true} else return false"><select name="%s"><option value="">%s</option>%s</select> <input type="submit" value="%s" /></form>',
  782.                        $this->linkTarget,
  783.                        'HTML_TreeMenu_Listbox_' . ++$count,
  784.                        'HTML_TreeMenu_Listbox_' . $count,
  785.                        'HTML_TreeMenu_Listbox_' . $count,
  786.                        $this->promoText,
  787.                        $nodeHTML,
  788.                        $this->submitText);
  789.     }
  790.  
  791.     /**
  792.     * Returns HTML for a single node
  793.     *
  794.     * @access private
  795.     */
  796.     function _nodeToHTML($node, $prefix = '')
  797.     {
  798.         $html = sprintf('<option value="%s">%s%s</option>', $node->link, $prefix, $node->text);
  799.  
  800.         /**
  801.         * Loop through subnodes
  802.         */
  803.         if (isset($node->items)) {
  804.             for ($i=0; $i<count($node->items); $i++) {
  805.                 $html .= $this->_nodeToHTML($node->items[$i], $prefix . str_repeat($this->indentChar, $this->indentNum));
  806.             }
  807.         }
  808.  
  809.         return $html;
  810.     }
  811. } // End class HTML_TreeMenu_Listbox
  812. ?>
  813.